package ru.susu.algebra.centralunits.alternating.characters;

import java.math.BigInteger;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.ObjectUtils;
import org.apache.log4j.Logger;

import com.google.common.collect.Lists;

import ru.susu.algebra.centralunits.CentralUnitsOptions;
import ru.susu.algebra.centralunits.alternating.MathMethodWithInitializers;
import ru.susu.algebra.centralunits.alternating.initializers.SpecialRowsInitializer;
import ru.susu.algebra.centralunits.alternating.tex.HeadAnTexGenerator;
import ru.susu.algebra.chartable.constructor.AlternatingCharTableUtil;
import ru.susu.algebra.field.quadratic.QuadraticFieldGeneralForm;
import ru.susu.algebra.jtex.ITexDocument;
import ru.susu.algebra.jtex.ITexElement;
import ru.susu.algebra.jtex.StringTexElement;
import ru.susu.algebra.jtex.TexDocument;
import ru.susu.algebra.jtex.TexElementWithCode;
import ru.susu.algebra.jtex.UnionTexElement;
import ru.susu.algebra.jtex.formula.GreekSymbols;
import ru.susu.algebra.jtex.utils.TexUtils;
import ru.susu.algebra.methods.IMathMethodPS;
import ru.susu.algebra.partition.Partition;
import ru.susu.algebra.properties.IPropertySource;
import ru.susu.algebra.properties.MapPropertySource;
import ru.susu.algebra.util.CollectionUtils;

/**
 * @author akargapolov
 * @since: 05.10.2010
 */
public class SpecialCharactersSearcher implements IMathMethodPS<ITexDocument>
{
	private static final Logger _log = Logger.getLogger("special_characters");

	private static final int NUMBER = 60;

	private MathMethodWithInitializers<ITexElement> method = new MathMethodWithInitializers<ITexElement>()
	{
		@Override
		protected ITexElement directRun(IPropertySource ps) throws Exception
		{
			List<Partition> rows = SpecialRowsInitializer.listSpecialNotIntegerCharacterRows(ps);
			if (rows.isEmpty())
			{
				return null;
			}
			UnionTexElement union = UnionTexElement.union();
			union.addSubElement(TexElementWithCode.section().setNotNumbered().addSubElement(StringTexElement.text("$A_{" + ps.getValue(CentralUnitsOptions.NUMBER) + "}$")))
					 .addSubElement(StringTexElement.newLineDouble());
			for (Partition partition : rows)
			{
				int index = SpecialRowsInitializer.getRowNumber(ps, partition);
				Partition column = AlternatingCharTableUtil.getColumn4SpecialRow(partition);
				QuadraticFieldGeneralForm character = AlternatingCharTableUtil.getSpecialCharacter(partition);
				String texColumn = CollectionUtils.toString(Lists.newArrayList(column.getArrayRepresentation()), "\\text{ }");
				if (!ObjectUtils.equals(character.getTrace(), BigInteger.ONE))
				{
					throw new RuntimeException("Trace is not one");
				}
				union.addSubElement(StringTexElement.text("$" + GreekSymbols.CHI + TexUtils.index(index) + TexUtils.inBrackets(texColumn) + " = " +
						TexUtils.toTexString(character) + "$")).addSubElement(StringTexElement.newLineDouble());
			}
			return union;
		}

		@Override
		protected Class[] getDependentInitializers()
		{
			return new Class[]{SpecialRowsInitializer.class};
		}
	};

	@Override
	public ITexDocument run(IPropertySource ps) throws Exception
	{
		ITexDocument document = new TexDocument();
		//стили и настройки
		document.setHead(new HeadAnTexGenerator().run(ps)).newLine();

		//название
		document.addElement(TexElementWithCode.section().setNotNumbered().addSubElement(StringTexElement.text("Нужные значения особых характеров $A_n$")));

		for (int i = 1; i <= NUMBER; i++)
		{
			_log.info("Start for " + i);
			Date start = new Date();

			MapPropertySource mps = new MapPropertySource();
			mps.setValue(CentralUnitsOptions.NUMBER, i);

			ITexElement element = method.run(mps);
			if (element != null)
			{
				document.addElement(element);
			}

			_log.info("End " + i + " - " + (new Date().getTime() - start.getTime()) + "ms");
		}

		return document;
	}

}
